package com.zhaojun.cloud.common.util;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.*;

public class ArrayUtil extends ArrayUtils {

	public static final String COMMA = CommonUtil.COMMA;
	public static final String DELIMITER = COMMA;
	public static final String DEFAULT_DELIMITER = CommonUtil.DEFAULT_DELIMITER;

	public static List<Long[]> grouping(Long[] values, int groupSize) {
		if (ArrayUtils.isEmpty(values)) {
			return null;
		}
		AssertionEx.isPositive(groupSize, "divideSize must be bigger than 0");
		int len = values.length;
		int groupLength = len / groupSize + ((len % groupSize) > 0 ? 1 : 0);
		List<Long[]> longArryGroup = new LinkedList<>();
		Long[] valueArray = null;
		for (int i = 0; i < groupLength; i++) {
			int arrayLength = (i < groupLength - 1 || len % groupSize == 0) ? groupSize : (len % groupSize);

			valueArray = new Long[arrayLength];
			for (int j = 0; j < arrayLength; j++) {
				valueArray[j] = values[i * groupSize + j];
			}
			longArryGroup.add(valueArray);
		}
		return longArryGroup;
	}

	public static String join(Long[] values) {
		return join(values, DEFAULT_DELIMITER);
	}

	public static String join(Long[] values, String delimiter) {
		return StringUtils.join(values, delimiter);
	}

	public static String join(short[] values) {
		return join(values, DEFAULT_DELIMITER);
	}

	public static String join(short[] values, String delimiter) {
		return StringUtils.join(ArrayUtils.toObject(values), delimiter);
	}

	public static String join(String[] values) {
		return StringUtils.join(values, DELIMITER);
	}

	public static Long[] escapeDuplication(Long[] values) {
		if (ArrayUtils.isEmpty(values)) {
			return null;
		}
		Set<Long> set = new LinkedHashSet<>();
		set.addAll(Arrays.asList(values));
		return set.toArray(new Long[0]);
	}

	public static long[] escapeDuplication(long[] values) {
		if (ArrayUtils.isEmpty(values)) {
			return null;
		}
		Set<Long> set = new LinkedHashSet<>();
		set.addAll(Arrays.asList(ArrayUtils.toObject(values)));
		return ArrayUtils.toPrimitive(set.toArray(new Long[0]));
	}

	public static short[] safeArray(short[] values) {
		if (null == values) {
			values = new short[0];
		}
		return values;
	}

	public static int[] safeArray(int[] values) {
		if (null == values) {
			values = new int[0];
		}
		return values;
	}

	public static long[] safeArray(long[] values) {
		if (null == values) {
			values = new long[0];
		}
		return values;
	}

	public static double[] safeArray(double[] values) {
		if (null == values) {
			values = new double[0];
		}
		return values;
	}

	/**
	 * 判断数组是否完全包含在另一数组中
	 * 
	 * @param array
	 * @param arrayToFind
	 *            被包含的数组[可能存在重复元素，所以可能比array要长]
	 * @return
	 */
	public static boolean contains(String[] array, String[] arrayToFind) {
		if (array == null || arrayToFind == null) {
			return false;
		}
		for (int i = 0; i < arrayToFind.length; i++) {
			if (!ArrayUtils.contains(array, arrayToFind[i])) {
				return false;
			}
		}
		return true;
	}


	@SuppressWarnings("unchecked")
	public static <T> T[] concat(T[] first, T[]... others) {
		if (Detect.isEmpty(first) && Detect.isEmpty(others)) {
			return null;
		}

		if (Detect.notEmpty(first) && Detect.isEmpty(others)) {
			return first;
		}

		if (Detect.isEmpty(first) && Detect.notEmpty(others) && others.length == 1) {
			return others[0];
		}

		T[] results = Detect.notEmpty(first) ? first : null;

		for (T[] other : others) {
			if (results == null) {
				results = other;
			} else {
				results = ArrayUtils.addAll(results, other);
			}
		}

		return results;
	}

	public static short[] toShortArray(String value) {
		return toShortArray(value, DELIMITER);
	}

	public static short[] toShortArray(String value, char delimiter) {
		if (!Detect.notEmpty(value)) {
			return null;
		}
		String[] values = StringUtils.split(value, delimiter);

		short[] shortValues = new short[values.length];
		for (int i = 0; i < values.length; i++) {
			shortValues[i] = Short.parseShort(values[i]);
		}
		return shortValues;
	}

	public static short[] toShortArray(String value, String delimiter) {
		if (!Detect.notEmpty(value)) {
			return null;
		}
		String[] values = StringUtils.split(value, delimiter);

		short[] shortValues = new short[values.length];
		for (int i = 0; i < values.length; i++) {
			if (Detect.notEmpty(values[i])) {
				shortValues[i] = Short.parseShort(values[i].trim());
			}
		}
		return shortValues;
	}

	public static Long[] toLongArray(String value) {
		return toLongArray(value, DELIMITER);
	}

	public static long[] toLongArray(String value, char delimiter) {
		if (!Detect.notEmpty(value)) {
			return null;
		}
		String[] values = StringUtils.split(value, delimiter);

		long[] longValues = new long[values.length];
		for (int i = 0; i < values.length; i++) {
			longValues[i] = Long.parseLong(values[i]);
		}
		return longValues;
	}

	public static Long[] toLongArray(String value, String delimiter) {
		if (!Detect.notEmpty(value)) {
			return null;
		}
		String[] values = StringUtils.split(value, delimiter);

		Long[] longValues = new Long[values.length];
		for (int i = 0; i < values.length; i++) {
			if (Detect.notEmpty(values[i])) {
				longValues[i] = Long.parseLong(values[i].trim());
			}
		}
		return longValues;
	}

	public static long[] toPrimitiveLongArray(Collection<Long> collection) {
		return ArrayUtils.toPrimitive(toLongArray(collection));
	}

	public static Long[] toLongArray(Collection<Long> collection) {
		if (Detect.notEmpty(collection)) {
			return collection.toArray(new Long[collection.size()]);
		}
		return null;
	}

	public static Long[] merger(Long[] arr1, Long[] arr2) {
		if (Detect.isEmpty(arr1) && Detect.isEmpty(arr2)) {
			return null;
		}

		Set<Long> set = new HashSet<>();
		if (Detect.notEmpty(arr1)) {
			for (Long l : arr1) {
				set.add(l);
			}
		}

		if (Detect.notEmpty(arr2)) {
			for (Long l : arr2) {
				set.add(l);
			}
		}

		return set.toArray(new Long[set.size()]);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Object> T convertToObject(byte[] bytes) {
		T t = null;
		if (bytes != null) {
			ByteArrayInputStream byteArrayInputputStream = null;
			ObjectInputStream objectInputStream = null;
			try {
				byteArrayInputputStream = new ByteArrayInputStream(bytes);
				objectInputStream = new ObjectInputStream(byteArrayInputputStream);

				t = (T) objectInputStream.readObject();
			} catch (Exception ex) {
				throw new RuntimeException(ex);
			} finally {
				if (objectInputStream != null) {
					try {
						objectInputStream.close();
					} catch (IOException e) {
					}
				}

				if (byteArrayInputputStream != null) {
					try {
						byteArrayInputputStream.close();
					} catch (IOException e) {
					}
				}
			}
		}
		return t;
	}

	/**
	 * 把一个数组拆分为多个数组
	 * 
	 * @param array
	 *            要拆分的数组
	 * @param arraySize
	 *            每个数组的大小
	 * @return
	 */
	public static String[][] splitArray(String[] array, int arraySize) {
		if (Detect.notEmpty(array)) {
			if (1 > arraySize) {
				throw new IllegalArgumentException("数组大小不能小于1");
			}
			int blockCount = array.length / arraySize;
			if (0 < array.length % arraySize) {
				blockCount++;
			}
			String[][] result = new String[blockCount][];

			for (int i = 0; i < blockCount; i++) {
				int bottom = i * arraySize;
				int top = bottom + arraySize - 1;
				top = top < array.length - 1 ? top : array.length - 1;

				String[] tmpArray = new String[top - bottom + 1];

				for (int j = bottom; j <= top; j++) {
					tmpArray[j - bottom] = array[j];
				}

				result[i] = tmpArray;
			}

			return result;
		} else {
			throw new IllegalArgumentException("数组不能为空");
		}
	}
}
